/**
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 */
package com.ld.shieldsb.common.core.io;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.activation.MimetypesFileTypeMap;

import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.encryptor.EncodeUtils;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.os.OSType;
import com.ld.shieldsb.common.core.util.os.OSUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件操作工具类 实现文件的创建、删除、复制、压缩、解压以及目录的创建、删除、复制、压缩解压等功能
 * 
 * @author ThinkGem
 * @version 2015-3-16
 */
@Slf4j
public class FileUtils extends org.apache.commons.io.FileUtils {
    /**
     * 当前目录路径
     */
    public static final String currentWorkDir = System.getProperty("user.dir") + "/";

    /**
     * 复制单个文件，如果目标文件存在，则不覆盖
     * 
     * @param srcFileName
     *            待复制的文件名
     * @param descFileName
     *            目标文件名
     * @return 如果复制成功，则返回true，否则返回false
     */
    public static boolean copyFile(String srcFileName, String descFileName) {
        return FileUtils.copyFileCover(srcFileName, descFileName, false);
    }

    /**
     * 复制单个文件
     * 
     * @param srcFileName
     *            待复制的文件名
     * @param destFileName
     *            目标文件名
     * @param coverlay
     *            如果目标文件已存在，是否覆盖
     * @return 如果复制成功，则返回true，否则返回false
     */
    public static boolean copyFileCover(String srcFileName, String destFileName, boolean coverlay) {
        File srcFile = new File(srcFileName);
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            log.debug("复制文件失败，源文件 " + srcFileName + " 不存在!");
            return false;
        }
        // 判断源文件是否是合法的文件
        else if (!srcFile.isFile()) {
            log.debug("复制文件失败，" + srcFileName + " 不是一个文件!");
            return false;
        }
        File destFile = new File(destFileName);
        // 判断目标文件是否存在
        if (destFile.exists()) {
            // 如果目标文件存在，并且允许覆盖
            if (coverlay) {
                log.debug("目标文件已存在，准备删除!");
                if (!FileUtils.delFile(destFileName)) {
                    log.debug("删除目标文件 " + destFileName + " 失败!");
                    return false;
                }
            } else {
                log.debug("复制文件失败，目标文件 " + destFileName + " 已存在!");
                return false;
            }
        } else {
            if (!destFile.getParentFile().exists()) {
                // 如果目标文件所在的目录不存在，则创建目录
                log.debug("目标文件所在的目录不存在，创建目录!");
                // 创建目标文件所在的目录
                if (!destFile.getParentFile().mkdirs()) {
                    log.debug("创建目标文件所在的目录失败!");
                    return false;
                }
            }
        }

        try {
            copyFile(srcFile, destFile);
            log.debug("复制单个文件 " + srcFileName + " 到" + destFileName + "成功!");
            return true;
        } catch (Exception e) {
            log.debug("复制文件失败：" + e.getMessage());
            return false;
        }
    }

    /**
     * 复制整个目录的内容，如果目标目录存在，则不覆盖
     * 
     * @param srcDirName
     *            源目录名
     * @param descDirName
     *            目标目录名
     * @return 如果复制成功返回true，否则返回false
     */
    public static boolean copyDirectory(String srcDirName, String descDirName) {
        return FileUtils.copyDirectoryCover(srcDirName, descDirName, false);
    }

    /**
     * 复制整个目录的内容
     * 
     * @param srcDirName
     *            源目录名
     * @param descDirName
     *            目标目录名
     * @param coverlay
     *            如果目标目录存在，是否覆盖
     * @return 如果复制成功返回true，否则返回false
     */
    public static boolean copyDirectoryCover(String srcDirName, String descDirName, boolean coverlay) {
        File srcDir = new File(srcDirName);
        // 判断源目录是否存在
        if (!srcDir.exists()) {
            log.debug("复制目录失败，源目录 " + srcDirName + " 不存在!");
            return false;
        }
        // 判断源目录是否是目录
        else if (!srcDir.isDirectory()) {
            log.debug("复制目录失败，" + srcDirName + " 不是一个目录!");
            return false;
        }
        // 如果目标文件夹名不以文件分隔符结尾，自动添加文件分隔符
        String descDirNames = descDirName;
        if (!descDirNames.endsWith(File.separator)) {
            descDirNames = descDirNames + File.separator;
        }
        File descDir = new File(descDirNames);
        // 如果目标文件夹存在
        if (descDir.exists()) {
            if (coverlay) {
                // 允许覆盖目标目录
                log.debug("目标目录已存在，准备删除!");
                if (!FileUtils.delFile(descDirNames)) {
                    log.debug("删除目录 " + descDirNames + " 失败!");
                    return false;
                }
            } else {
                log.debug("目标目录复制失败，目标目录 " + descDirNames + " 已存在!");
                return false;
            }
        } else {
            // 创建目标目录
            log.debug("目标目录不存在，准备创建!");
            if (!descDir.mkdirs()) {
                log.debug("创建目标目录失败!");
                return false;
            }

        }

        boolean flag = true;
        // 列出源目录下的所有文件名和子目录名
        File[] files = srcDir.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 如果是一个单个文件，则直接复制
            if (files[i].isFile()) {
                flag = FileUtils.copyFile(files[i].getAbsolutePath(), descDirName + files[i].getName());
                // 如果拷贝文件失败，则退出循环
                if (!flag) {
                    break;
                }
            }
            // 如果是子目录，则继续复制目录
            if (files[i].isDirectory()) {
                flag = FileUtils.copyDirectory(files[i].getAbsolutePath(), descDirName + files[i].getName());
                // 如果拷贝目录失败，则退出循环
                if (!flag) {
                    break;
                }
            }
        }

        if (!flag) {
            log.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 失败!");
            return false;
        }
        log.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 成功!");
        return true;

    }

    /**
     * 
     * 删除文件，可以删除单个文件或文件夹
     * 
     * @param fileName
     *            被删除的文件名
     * @return 如果删除成功，则返回true，否是返回false
     */
    public static boolean delFile(String fileName) {
        File file = new File(fileName);
        if (!file.exists()) {
            log.debug(fileName + " 文件不存在!");
            return true;
        } else {
            if (file.isFile()) {
                return FileUtils.delete(fileName);
            } else {
                return FileUtils.deleteDirectory(fileName);
            }
        }
    }

    /**
     * 
     * 删除单个文件
     * 
     * @param fileName
     *            被删除的文件名
     * @return 如果删除成功，则返回true，否则返回false
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                log.debug("删除文件 " + filePath + " 成功!");
                return true;
            } else {
                log.debug("删除文件 " + filePath + " 失败!");
                return false;
            }
        } else {
            log.debug(filePath + " 文件不存在!");
            return true;
        }
    }

    /**
     * 删除文件（如果删除后父目录为空则一并删除）
     * 
     * @Title deleteCaseParent
     * @author 吕凯
     * @date 2019年2月14日 上午11:20:14
     * @param filePath
     * @return boolean
     */
    public static boolean deleteCaseParent(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            File parentFile = file.getParentFile();
            File[] files = parentFile.listFiles();
            if (files.length == 1) {
                file.delete();
                deleteEmptyParent(parentFile);
                return true;
            } else {
                return file.delete();
            }
        }
        return false;
    }

    /**
     * 删除空的父目录
     * 
     * @Title deleteEmptyParent
     * @author 吕凯
     * @date 2019年2月14日 上午11:19:53
     * @param file
     *            void
     */
    public static void deleteEmptyParent(File file) {
        File[] files = file.listFiles();
        if (files.length == 0) {
            File parentFile = file.getParentFile();
            file.delete();
            if (parentFile != null) {
                deleteEmptyParent(parentFile);
            }
        }
    }

    /**
     * 
     * 删除目录及目录下的文件
     * 
     * @param dirName
     *            被删除的目录所在的文件路径
     * @return 如果目录删除成功，则返回true，否则返回false
     */
    public static boolean deleteDirectory(String dirName) {
        String dirNames = dirName;
        if (!dirNames.endsWith(File.separator)) {
            dirNames = dirNames + File.separator;
        }
        File dirFile = new File(dirNames);
        try {
            deleteDirectory(dirFile);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("", e);
            return false;
        }

    }

    /**
     * 创建单个文件
     * 
     * @param descFileName
     *            文件名，包含路径
     * @return 如果创建成功，则返回true，否则返回false
     */
    public static boolean createFile(String descFileName) {
        File file = new File(descFileName);
        if (file.exists()) {
            log.debug("文件 " + descFileName + " 已存在!");
            return false;
        }
        if (descFileName.endsWith(File.separator)) {
            log.debug(descFileName + " 为目录，不能创建目录!");
            return false;
        }
        if (!file.getParentFile().exists()) {
            // 如果文件所在的目录不存在，则创建目录
            if (!file.getParentFile().mkdirs()) {
                log.debug("创建文件所在的目录失败!");
                return false;
            }
        }

        // 创建文件
        try {
            if (file.createNewFile()) {
                log.debug(descFileName + " 文件创建成功!");
                return true;
            } else {
                log.debug(descFileName + " 文件创建失败!");
                return false;
            }
        } catch (Exception e) {
            log.error("", e);
            log.debug(descFileName + " 文件创建失败!");
            return false;
        }

    }

    /**
     * 创建目录
     * 
     * @param descDirName
     *            目录名,包含路径
     * @return 如果创建成功，则返回true，否则返回false
     */
    public static boolean createDirectory(String descDirName) {
        String descDirNames = descDirName;
        if (!descDirNames.endsWith(File.separator)) {
            descDirNames = descDirNames + File.separator;
        }
        File descDir = new File(descDirNames);
        if (descDir.exists()) {
            log.debug("目录 " + descDirNames + " 已存在!");
            return false;
        }
        // 创建目录
        if (descDir.mkdirs()) {
            log.debug("目录 " + descDirNames + " 创建成功!");
            return true;
        } else {
            log.debug("目录 " + descDirNames + " 创建失败!");
            return false;
        }

    }

    /**
     * 写入文件（utf-8编码）
     * 
     * @Title writeToFile
     * @author 吕凯
     * @date 2019年3月12日 下午2:04:53
     * @param fileName
     * @param content
     *            void
     */
    public static boolean writeToFile(String fileName, String content) {
        return writeToFile(fileName, content, "utf-8", false);
    }

    /**
     * 写入文件
     * 
     * @Title writeToFile
     * @author 吕凯
     * @date 2019年3月12日 下午2:04:02
     * @param fileName
     * @param content
     * @param encoding
     *            void
     */
    public static boolean writeToFile(String fileName, String content, String encoding) {
        return writeToFile(fileName, content, encoding, false);
    }

    /**
     * 写入文件
     * 
     * @param file
     *            要写入的文件
     */
    public static boolean writeToFile(String fileName, String content, boolean append) {
        return writeToFile(fileName, content, "utf-8", append);
    }

    /**
     * 写入文件
     * 
     * @param file
     *            要写入的文件
     */
    public static boolean writeToFile(String fileName, String content, String encoding, boolean append) {
        try {
            FileUtils.write(new File(fileName), content, encoding, append);
            log.debug("文件 " + fileName + " 写入成功!");
            return true;
        } catch (IOException e) {
            log.debug("文件 " + fileName + " 写入失败! " + e.getMessage());
        }
        return false;
    }

    /**
     * 根据图片Base64写入图片文件
     * 
     * @param fileName
     *            写入的文件路径及文件名
     * @param imageBase64
     *            图片Base64字符串
     */
    public static void writeToFileByImageBase64(String fileName, String imageBase64) {
        String base64 = StringUtils.substringAfter(imageBase64, "base64,");
        if (StringUtils.isBlank(base64)) {
            return;
        }
        byte[] data = EncodeUtils.decodeBase64(base64);

        File file = new File(fileName);
        try {
            FileUtils.writeByteArrayToFile(file, data);
        } catch (IOException e) {
            log.error("", e);
        }
    }

    /**
     * 根据文件名的后缀获取文件内容类型
     * 
     * @return 返回文件类型
     */
    public static String getContentType(String fileName) {
        return new MimetypesFileTypeMap().getContentType(fileName);
    }

    /**
     * 修正路径，将 \\ 或 / 等替换为 File.separator
     * 
     * @param path
     *            待修正的路径
     * @return 修正后的路径
     */
    public static String path(String path) {
        String p = StringUtils.replace(path, "\\", "/");
        p = StringUtils.join(StringUtils.split(p, "/"), "/");
        if (!StringUtils.startsWithAny(p, "/") && StringUtils.startsWithAny(path, "\\", "/")) {
            p += "/";
        }
        if (!StringUtils.endsWithAny(p, "/") && StringUtils.endsWithAny(path, "\\", "/")) {
            p = p + "/";
        }
        if (path != null && path.startsWith("/")) {
            p = "/" + p; // linux下路径
        }
        return p;
    }

    /**
     * 获目录下的文件列表(只显示文件或目录)
     * 
     * @param dir
     *            搜索目录
     * @param searchDirs
     *            是否是搜索目录，true之搜索目录，false只搜索文件
     * @return 文件列表
     */
    public static List<String> findChildrenList(File dir, boolean searchDirs) {
        List<String> files = ListUtils.newArrayList();
        for (String subFiles : dir.list()) {
            File file = new File(dir + "/" + subFiles);
            if ((searchDirs && file.isDirectory()) || (!searchDirs && !file.isDirectory())) {
                files.add(file.getName());
            }
        }
        return files;
    }

    /**
     * 获取文件名(带扩展名)
     * 
     * @param pathname
     *            文件路径名
     */
    public static String getFileName(String fileName) {
        return new File(fileName).getName();
    }

    /**
     * 获取文件名，不包含扩展名
     * 
     * @param fileName
     *            文件名
     * @return 例如：d:\files\test.jpg 返回：d:\files\test
     */
    public static String getFileNameWithoutExtension(String fileName) {
        if ((fileName == null) || (fileName.lastIndexOf(".") == -1)) {
            return null;
        }
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * 获取文件扩展名(返回小写)
     * 
     * @param pathname
     *            文件名
     * @return 例如：test.jpg 返回： jpg
     */
    public static String getFileExtension(String fileName) {
        if ((fileName == null) || (fileName.lastIndexOf(".") == -1) || (fileName.lastIndexOf(".") == fileName.length() - 1)) {
            return null;
        }
        return StringUtils.lowerCase(fileName.substring(fileName.lastIndexOf(".") + 1));
    }

    /**
     * 根据图片Base64获取文件扩展名
     * 
     * @param imageBase64
     * @return
     * @author ThinkGem
     */
    public static String getFileExtensionByImageBase64(String imageBase64) {
        String extension = null;
        String type = StringUtils.substringBetween(imageBase64, "data:", ";base64,");
        if (StringUtils.inStrArrIgnoreCase(type, "image/jpeg")) {
            extension = "jpg";
        } else if (StringUtils.inStrArrIgnoreCase(type, "image/gif")) {
            extension = "gif";
        } else {
            extension = "png";
        }
        return extension;
    }

    /**
     * 判断文件是否存在
     *
     * @param fileName
     * @return
     */
    public static boolean exists(String fileName) {
        File f = new File(fileName);
        return f.exists();
    }

    /**
     * 获取jar包的执行路径
     * 
     * @Title getJarExecPath
     * @author 吕凯
     * @date 2019年8月1日 下午3:05:52
     * @param clazz
     * @return String
     */
    public static String getJarExecPath(Class<?> clazz) {
        String path = clazz.getProtectionDomain().getCodeSource().getLocation().getPath();
        if (OSUtil.getOSType().equals(OSType.Windows)) {
            return path.substring(1);
        }
        return path;
    }

    /**
     * 根据完整文件名，得到文件所在目录
     *
     * @param filePath
     * @return
     */
    public static String getDirName(String filePath) {
        File f = new File(filePath);
        return f.getParent();
    }

    /**
     * 加载classPath下的属性文件
     *
     * @param fileName
     *            比如：“/properties/mail.properties”
     * @return
     * @throws Exception
     */
    public static Properties loadProperties(String fileName) {
        try {
            Properties p = new Properties();
            p.load(FileUtils.class.getResourceAsStream(fileName));
            return p;
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * 删除文件
     *
     * @param fileName
     *            待删除的完整文件名
     * @return
     */
    public static boolean delete(String fileName) {
        boolean result = false;
        File f = new File(fileName);
        if (f.exists()) {
            result = f.delete();

        } else {
            result = true;
        }
        return result;
    }

    /**
     * 递归获取指定目录下的所有的文件（不包括文件夹）
     *
     * @return
     */
    public static ArrayList<File> getAllFiles(String dirPath) {
        File dir = new File(dirPath);

        ArrayList<File> files = new ArrayList<File>();

        if (dir.isDirectory()) {
            File[] fileArr = dir.listFiles();
            for (int i = 0; i < fileArr.length; i++) {
                File f = fileArr[i];
                if (f.isFile()) {
                    files.add(f);
                } else {
                    files.addAll(getAllFiles(f.getPath()));
                }
            }
        }
        return files;
    }

    /**
     * 获取指定目录下的所有下一级子目录(不递归)
     *
     * @param dirPath
     * @return
     */
    public static ArrayList<File> getAllDirectory(String dirPath) {
        return getAllDirectory(dirPath, false);
    }

    /**
     * 获取指定路径下的所有目录
     *
     * @param dirPath
     * @param isRecursive
     * @return
     */
    public static ArrayList<File> getAllDirectory(String dirPath, boolean isRecursive) {
        File dir = new File(dirPath);
        ArrayList<File> files = new ArrayList<File>();
        if (dir.isDirectory()) {
            File[] fileArr = dir.listFiles();
            for (int i = 0; i < fileArr.length; i++) {
                File f = fileArr[i];
                if (f.isDirectory()) {
                    files.add(f);
                    if (isRecursive) {
                        files.addAll(getAllDirectory(f.getPath(), true));
                    }
                }
            }
        }
        return files;
    }

    /**
     * 获取指定目录下的所有文件(不包括子文件夹)
     *
     * @param dirPath
     * @return
     */
    public static ArrayList<File> getDirFiles(String dirPath) {
        File path = new File(dirPath);
        File[] fileArr = path.listFiles();
        ArrayList<File> files = new ArrayList<File>();

        if (fileArr == null) {
            return files;
        }

        for (File f : fileArr) {
            if (f.isFile()) {
                files.add(f);
            }
        }
        return files;
    }

    /**
     * 获取指定目录下特定文件后缀名的文件列表(不包括子文件夹)
     *
     * @param dirPath
     *            目录路径
     * @param suffix
     *            文件后缀
     * @return
     */
    public static List<File> getDirFiles(String dirPath, final String suffix) {
        File path = new File(dirPath);
        File[] fileArr = path.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                String lowerName = name.toLowerCase();
                String lowerSuffix = suffix.toLowerCase();
                if (lowerName.endsWith(lowerSuffix)) {
                    return true;
                }
                return false;
            }

        });
        List<File> files = new ArrayList<File>();

        for (File f : fileArr) {
            if (f.isFile()) {
                files.add(f);
            }
        }
        return files;
    }

    /**
     * 批量删除文件
     *
     * @param files
     */
    public static void delete(List<File> files) {
        for (int i = files.size() - 1; i >= 0; i--) {
            File f = files.get(i);
            log.debug("准备删除文件：" + f.getAbsolutePath());
            if (f.exists()) {
                if (f.delete()) {
                    log.debug("文件：" + f.getAbsolutePath() + " 删除成功！");
                } else {
                    log.debug("文件：" + f.getAbsolutePath() + " 删除失败！");
                }
            }
        }

    }

    /**
     * 通过前缀得到指定文件夹下的文件列表
     *
     * @param dirPath
     *            目录路径
     * @param prefix
     *            前缀
     * @return
     */
    public static List<File> getDirFilesByPrefix(String dirPath, final String prefix) {
        File path = new File(dirPath);
        File[] fileArr = path.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                String lowerName = name.toLowerCase();
                String lowerPrefix = prefix.toLowerCase();
                if (lowerName.startsWith(lowerPrefix)) {
                    return true;
                }
                return false;
            }

        });
        List<File> files = new ArrayList<File>();

        for (File f : fileArr) {
            if (f.isFile()) {
                files.add(f);
            }
        }
        return files;
    }

    /**
     * 通过前缀后后缀获取符合条件的文件
     * 
     * @Title getDirFilesByPrefixAndSurfix
     * @author 吕凯
     * @date 2019年8月1日 下午3:10:42
     * @param dirPath
     *            目录路径
     * @param prefix
     *            前缀
     * @param surfix
     *            后缀
     * @return List<File>
     */
    public static List<File> getDirFilesByPrefixAndSurfix(String dirPath, final String prefix, final String surfix) {
        File path = new File(dirPath);
        File[] fileArr = path.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                String lowerName = name.toLowerCase();
                String lowerPrefix = prefix.toLowerCase();
                String lowerSurfix = surfix.toLowerCase();
                if (lowerName.startsWith(lowerPrefix) && lowerName.endsWith(lowerSurfix)) {
                    return true;
                }
                return false;
            }

        });
        List<File> files = new ArrayList<File>();

        for (File f : fileArr) {
            if (f.isFile()) {
                files.add(f);
            }
        }
        return files;
    }

    /**
     * 获取目录下某前缀并排除一部分前缀的文件
     * 
     * @Title getDirFilesByPrefix
     * @author 吕凯
     * @date 2019年8月1日 下午3:12:34
     * @param dirPath
     *            目录
     * @param prefix
     *            搜索的前缀
     * @param execludePrefix
     *            排除的前缀
     * @return List<File>
     */
    public static List<File> getDirFilesByPrefix(String dirPath, final String prefix, final String execludePrefix) {
        File path = new File(dirPath);
        File[] fileArr = path.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                String lowerName = name.toLowerCase();
                String lowerPrefix = prefix.toLowerCase();
                String lowerExecludePrefix = execludePrefix.toLowerCase();
                if (lowerName.startsWith(lowerPrefix) && !lowerName.startsWith(lowerExecludePrefix)) {
                    return true;
                }
                return false;
            }

        });
        List<File> files = new ArrayList<File>();

        for (File f : fileArr) {
            if (f.isFile()) {
                files.add(f);
            }
        }
        return files;
    }

    /**
     * 获取文件文本内容
     *
     * @param fileName
     *            待读取的完整文件名
     * @return 文件内容
     * @throws IOException
     */
    public static String read(String fileName) throws IOException {
        File f = new File(fileName);
        if (!f.exists()) {
            return null;
        }
        return read(f, "UTF-8");
    }

    /**
     * 获取文件文本内容
     *
     * @param f
     * @return
     * @throws IOException
     */
    public static String read(File f, String encoding) throws IOException {
        return FileUtils.readFileToString(f, encoding);
    }

    /**
     * 写文件
     *
     * @param fileName
     *            目标文件名
     * @param fileContent
     *            写入的内容
     * @return
     * @throws IOException
     */
    public static void write(String fileName, String fileContent) throws IOException {
        write(fileName, fileContent.getBytes());
    }

    /**
     * 写文件
     *
     * @param fileName
     *            完整文件名(类似：/usr/a/b/c/d.txt)
     * @param contentBytes
     *            文件内容的字节数组
     * @return
     * @throws IOException
     */
    public static void write(String fileName, byte[] contentBytes) throws IOException {
        File f = new File(fileName);
        FileUtils.writeByteArrayToFile(f, contentBytes);
    }

    /**
     * 写文件
     * 
     * @Title write
     * @author 吕凯
     * @date 2019年8月3日 下午2:31:00
     * @param fileName
     * @param fileContent
     * @param encoding
     * @throws IOException
     *             void
     */
    public static void write(String fileName, String fileContent, String encoding) throws IOException {
        File f = new File(fileName);
        org.apache.commons.io.FileUtils.write(f, fileContent, encoding);
    }

    /**
     * 
     * 追加内容到指定文件
     * 
     * @Title append
     * @author 吕凯
     * @date 2019年8月1日 下午3:16:51
     * @param fileName
     *            文件路径
     * @param fileContent
     *            文件内容
     * @param createFileIfNoExist
     *            如果文件不存在是否创建
     * @throws IOException
     *             void
     */
    public static void append(String fileName, String fileContent, boolean createFileIfNoExist) throws IOException {
        File f = new File(fileName);
        if (f.exists()) {
            try (RandomAccessFile rFile = new RandomAccessFile(f, "rw")) {
                byte[] b = fileContent.getBytes();
                long originLen = f.length();
                rFile.setLength(originLen + b.length);
                rFile.seek(originLen);
                rFile.write(b);
            }
        } else if (createFileIfNoExist) {
            write(fileName, fileContent);
        }
    }

    /**
     * 
     * 追加内容到指定文件(如果文件不存在则创建)
     * 
     * @Title append
     * @author 吕凯
     * @date 2019年8月1日 下午3:17:34
     * @param fileName
     *            文件路径
     * @param fileContent
     *            文件内容
     * @throws IOException
     *             void
     */
    public static void append(String fileName, String fileContent) throws IOException {
        append(fileName, fileContent, true);
    }

    /**
     * 创建(多级)目录，如果文件已存在则直接返回
     *
     * @param filePath
     *            完整的文件名(类似：/usr/a/b/c/d.xml)
     */
    public static void createDirs(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            return;
        }
        File parent = file.getParentFile();
        if (parent != null && !parent.exists()) {
            parent.mkdirs();
        }
    }

    /**
     * 移动文件
     *
     * @param fileNameFrom
     * @param fileNameTo
     * @throws IOException
     */
    public static void moveFile(String fileNameFrom, String fileNameTo) throws IOException {
        moveFile(new File(fileNameFrom), new File(fileNameTo));
    }

    /**
     * 创建空的临时目录
     *
     * @return
     */
    public static File createTempDirectory() {
        final String tmpPath = System.getProperty("java.io.tmpdir");
        long current = System.currentTimeMillis();
        File tmpDir = new File(tmpPath + File.separator + "patchDir" + current);
        if (tmpDir.exists()) {
            if (!tmpDir.delete()) {
                log.warn("旧的临时目录删除失败：" + tmpDir.getAbsolutePath());
            }
            return createTempDirectory();
        }
        tmpDir.mkdirs();
        return tmpDir;
    }

    /**
     * 获取工程源文件所在路径
     * 
     * @return
     */
//    public static String getProjectPath() {
//        String projectPath = "";
//        try {
//            File file = ResourceUtils.getResource("").getFile();
//            if (file != null) {
//                while (true) {
//                    File f = new File(path(file.getPath() + "/src/main"));
//                    if (f.exists()) {
//                        break;
//                    }
//                    f = new File(path(file.getPath() + "/target/classes"));
//                    if (f.exists()) {
//                        break;
//                    }
//                    if (file.getParentFile() != null) {
//                        file = file.getParentFile();
//                    } else {
//                        break;
//                    }
//                }
//                projectPath = file.toString();
//            }
//        } catch (FileNotFoundException e) {
//            ;
//        } catch (IOException e) {
//            log.error("", e);
//        }
//        return projectPath;
//    }

    /**
     * 获取工程源文件所在路径
     * 
     * @return
     */
//    public static String getWebappPath() {
//        String webappPath = "";
//        try {
//            File file = ResourceUtils.getResource("").getFile();
//            if (file != null) {
//                while (true) {
//                    File f = new File(path(file.getPath() + "/WEB-INF/classes"));
//                    if (f.exists()) {
//                        break;
//                    }
//                    f = new File(path(file.getPath() + "/src/main/webapp"));
//                    if (f.exists()) {
//                        return f.getPath();
//                    }
//                    if (file.getParentFile() != null) {
//                        file = file.getParentFile();
//                    } else {
//                        break;
//                    }
//                }
//                webappPath = file.toString();
//            }
//        } catch (FileNotFoundException e) {
//            ;
//        } catch (IOException e) {
//            log.error("", e);
//        }
//        return webappPath;
//    }

}
